/*
 *
 *  MIT License
 *
 *  Copyright (c) 2017 Alibaba Group
 *
 *  Permission is hereby granted, free of charge, to any person obtaining a copy
 *  of this software and associated documentation files (the "Software"), to deal
 *  in the Software without restriction, including without limitation the rights
 *  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 *  copies of the Software, and to permit persons to whom the Software is
 *  furnished to do so, subject to the following conditions:
 *
 *  The above copyright notice and this permission notice shall be included in all
 *  copies or substantial portions of the Software.
 *
 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 *  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 *  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 *  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 *  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 *  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 *  SOFTWARE.
 *
 */

package com.tmall.ultraviewpager;


import com.tmall.ultraviewpager.utils.LogUtil;
import ohos.agp.components.*;
import ohos.agp.window.service.Display;
import ohos.agp.window.service.DisplayManager;
import ohos.utils.PlainArray;

import java.util.Optional;


public class UltraViewPagerAdapter extends PageSliderProvider {
    public interface UltraViewPagerCenterListener {
        void center();

        void resetPosition();
    }



    private static final int INFINITE_RATIO = 400;

    private PageSliderProvider adapter;
    private boolean enableLoop;
    private float multiScrRatio = Float.NaN;
    private boolean hasCentered;
    private int scrWidth;
    private int infiniteRatio;
    private UltraViewPagerCenterListener centerListener;

    private PlainArray viewArray = new PlainArray<>();

    public UltraViewPagerAdapter(PageSliderProvider adapter) {
        this.adapter = adapter;
        infiniteRatio = INFINITE_RATIO;
    }

    @Override
    public int getCount() {
        int count;
        if (enableLoop) {
            if (adapter.getCount() == 0) {
                count = 0;
            } else {
                count = adapter.getCount() * infiniteRatio;
            }
        } else {
            count = adapter.getCount();
        }
        return count;
    }

    @Override
    public Object createPageInContainer(ComponentContainer container, int position) {
        int realPosition = position;

        if (enableLoop && adapter.getCount() != 0) {
            realPosition = position % adapter.getCount();
        }

        Object item = adapter.createPageInContainer(container, realPosition);

        Component childView = null;
        if (item instanceof Component)
            childView = (Component) item;


        int childCount = container.getChildCount();
        for (int i = 0; i < childCount; i++) {
            Component child = container.getComponentAt(i);
            if (isPageMatchToObject(child, item)) {
                viewArray.put(realPosition, child);
                break;
            }
        }

        if (isEnableMultiScr()) {
            if (scrWidth == 0) {
                Optional<Display> defaultDisplay = DisplayManager.getInstance().getDefaultDisplay(container.getContext());
                if(defaultDisplay.isPresent()){
                    scrWidth=defaultDisplay.get().getAttributes().width;
                }

            }
            DependentLayout relativeLayout = new DependentLayout(container.getContext());

            if (childView.getLayoutConfig() != null) {
                DependentLayout.LayoutConfig layoutParams = new DependentLayout.LayoutConfig(
                        (int) (scrWidth * multiScrRatio),
                        DependentLayout.LayoutConfig.MATCH_PARENT);

                layoutParams.addRule(DependentLayout.LayoutConfig.CENTER_IN_PARENT, DependentLayout.LayoutConfig.TRUE);
                childView.setLayoutConfig(layoutParams);
            }

            container.removeComponent(childView);
            relativeLayout.addComponent(childView);

            container.addComponent(relativeLayout);
            return relativeLayout;
        }

        return item;
    }

    @Override
    public void destroyPageFromContainer(ComponentContainer container, int position, Object object) {
        int realPosition = position;

        if (enableLoop && adapter.getCount() != 0)
            realPosition = position % adapter.getCount();

        if (isEnableMultiScr() && object instanceof DependentLayout) {
            Component child = ((DependentLayout) object).getComponentAt(0);
            ((DependentLayout) object).removeAllComponents();
            adapter.destroyPageFromContainer(container, realPosition, child);
        } else {
            adapter.destroyPageFromContainer(container, realPosition, object);
        }

        viewArray.remove(realPosition);
    }

    @Override
    public boolean isPageMatchToObject(Component component, Object o) {
       return adapter.isPageMatchToObject(component, o);
    }



    public Component getViewAtPosition(int position) {
        return (Component) viewArray.get(position).get();
    }



    @Override
    public void onUpdateFinished(ComponentContainer container) {
        if (!hasCentered) {
            if (adapter.getCount() > 0 && getCount() > adapter.getCount()) {
                centerListener.center();
            }
        }
        hasCentered = true;
        adapter.onUpdateFinished(container);
    }


    @Override
    public void startUpdate(ComponentContainer container) {
        adapter.startUpdate(container);
    }

    @Override
    public String getPageTitle(int position) {
        int virtualPosition = position % adapter.getCount();

        return adapter.getPageTitle(virtualPosition);
    }




    @Override
    public void notifyDataChanged() {
        super.notifyDataChanged();
        adapter.notifyDataChanged();
    }



    @Override
    public int getPageIndex(Object object) {
        return adapter.getPageIndex(object);
    }

    public PageSliderProvider getAdapter() {
        return adapter;
    }

    public int getRealCount() {
        return adapter.getCount();
    }

    public void setEnableLoop(boolean status) {
        this.enableLoop = status;
        notifyDataChanged();
        if (!status) {
            centerListener.resetPosition();
        } else {
            LogUtil.error("UltraViewPager","取消无限循环");
        }
    }

    public boolean isEnableLoop() {
        return enableLoop;
    }

    public void setMultiScrRatio(float ratio) {
        multiScrRatio = ratio;
    }

    public boolean isEnableMultiScr() {
        return !Float.isNaN(multiScrRatio) && multiScrRatio < 1f;
    }

    public void setCenterListener(UltraViewPagerCenterListener listener) {
        centerListener = listener;
    }

    public void setInfiniteRatio(int infiniteRatio) {
        this.infiniteRatio = infiniteRatio;
    }
}
